home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 April: Mac OS SDK / Dev.CD Apr 98 SDK2.toast / Development Kits (Disc 2) / QuickTime / Programming Stuff / Documentation / develop articles / develop Issue 23 / Internet Config / IC 1.1 / ICAppSourceKit1.1 / ICTextWhats.p < prev    next >
Encoding:
Text File  |  1997-02-26  |  12.4 KB  |  455 lines  |  [TEXT/PJMM]

  1. unit ICTextWhats;
  2.  
  3. interface
  4.  
  5.     uses
  6.         ICWindowGlobals;
  7.  
  8.     function WhatOpenText (wt: WindowType; item: integer): OSErr;
  9.     function WhatFlushText (wt: WindowType; item: integer): OSErr;
  10.     function WhatCloseText (wt: WindowType; item: integer): OSErr;
  11.     function WhatClickText (wt: WindowType; item: integer; er: eventRecord): OSErr;
  12.     function WhatKeyText (wt: WindowType; item: integer; er: EventRecord): OSErr;
  13.  
  14.     (* danger, layer break! *)
  15.     function HaveTextSelection (wt: WindowType): boolean;
  16.     procedure AdjustTextMenu (wt: WindowType);
  17.     procedure DoTextMenu (wt: WindowType; menuitem: integer);
  18.     procedure SelectTextItem (wt: WindowType; item: integer);
  19.  
  20. implementation
  21.  
  22.     uses
  23.         ICTypes, ICAPI, 
  24.  
  25.         ICGlobals, ICMiscSubs, ICSubs, ICText, ICDialogs, ICDocUtils;
  26.  
  27.     const
  28.         tf_single_line = 0;
  29.         tf_pstring = 1;
  30.         tf_scrambled = 2;
  31.         tf_monospace = 3;
  32.  
  33.         tf_single_line_mask = $0001;
  34.         tf_pstring_mask = $0002;
  35.         tf_scrambled_mask = $0004;
  36.         tf_monospace_mask = $0008;
  37.  
  38.     procedure DrawTextProc (window: DialogPtr; item: integer);
  39.         var
  40.             r: Rect;
  41.             savefont, savemode, savesize: integer;
  42.             saveface: Style;
  43.     begin
  44.         savefont := window^.txFont;
  45.         saveface := window^.txFace;
  46.         savemode := window^.txMode;
  47.         savesize := window^.txSize;
  48.         TextDraw(windowinfo[GetWindowType(window)].items[item]^.data);
  49.  
  50.         GetDItemRect(window, item, r);
  51.         InsetRect(r, -3, -3);
  52.         PenNormal;
  53.         FrameRect(r);
  54.         TextFont(savefont);
  55.         TextFace(saveface);
  56.         TextMode(savemode);
  57.         TextSize(savesize);
  58.     end;
  59.  
  60.     function HaveTextSelection (wt: WindowType): boolean;
  61.         var
  62.             start_sel, end_sel: integer;
  63.     begin
  64.         HaveTextSelection := false;
  65.         if GetSelectedItem(wt) > 0 then begin
  66.             TextGetSelect(windowinfo[wt].items[GetSelectedItem(wt)]^.data, start_sel, end_sel);
  67.             HaveTextSelection := (start_sel <> end_sel);
  68.         end; (* if *)
  69.     end; (* HaveTextSelection *)
  70.  
  71.     procedure AdjustTextMenu (wt: WindowType);
  72.         var
  73.             enable_cut, enable_paste, enable_select_all: boolean;
  74.             offset: longint;
  75.             mh: MenuHandle;
  76.             texth: Handle;
  77.             text_size: longint;
  78.             search_text: integer;
  79.             cr_pos: longint;
  80.             item: integer;
  81.             err: OSErr;
  82.             sel_start, sel_end: integer;
  83.     begin
  84.         item := GetSelectedItem(wt);
  85.         if (wt <> WT_None) & (item > 0) then begin
  86.             enable_cut := HaveTextSelection(wt);
  87.             offset := 0;
  88.             enable_paste := (GetScrap(nil, 'TEXT', offset) > 0);
  89.             TextGetSelect(windowinfo[wt].items[item]^.data, sel_start, sel_end);
  90.             TextGetSize(windowinfo[wt].items[item]^.data, text_size);
  91.             enable_select_all := (sel_start <> 0) or (sel_end <> text_size);
  92.         end
  93.         else begin
  94.             enable_cut := false;
  95.             enable_paste := false;
  96.             enable_select_all := false;
  97.         end; (* if *)
  98.         (* deal with the nasty paste problem, ie preventing them pasting CRs into single line fields *)
  99.         if enable_paste & btst(windowinfo[wt].items[item]^.flags, tf_single_line) then begin
  100.             texth := NewHandle(0);
  101.             err := MemError;
  102.             if err = noErr then begin
  103.                 offset := 0;
  104.                 text_size := GetScrap(texth, 'TEXT', offset);
  105.                 if text_size > 0 then begin
  106.                     search_text := $0D0D;
  107.                     cr_pos := Munger(texth, 0, @search_Text, 1, nil, 0);
  108.                     if cr_pos < 0 then begin
  109.                         enable_paste := true;
  110.                     end
  111.                     else if (cr_pos = text_size - 1) then begin
  112.                         enable_paste := (cr_pos > 0);
  113.                     end
  114.                     else begin
  115.                         enable_paste := false;
  116.                     end; (* if *)
  117.                 end
  118.                 else begin
  119.                     enable_paste := false;
  120.                 end; (* if *)
  121.             end; (* if *)
  122.             if texth <> nil then begin
  123.                 DisposeHandle(texth);
  124.             end; (* if *)
  125.             if err <> noErr then begin
  126.                 enable_paste := false;
  127.             end; (* if *)
  128.         end; (* if *)
  129.         (* deal with locked items *)
  130.         if item > 0 then begin
  131.             if IsLocked(wt, item) then begin
  132.                 enable_paste := false;
  133.                 enable_cut := false;
  134.             end; (* if *)
  135.         end; (* if *)
  136.         (* hit the menu items *)
  137.         mh := GetMHandle(M_Edit);
  138.         SetItemEnable(mh, EM_Undo, false);
  139.         SetItemEnable(mh, EM_Cut, enable_cut);
  140.         SetItemEnable(mh, EM_Copy, enable_cut);
  141.         SetItemEnable(mh, EM_Paste, enable_paste);
  142.         SetItemEnable(mh, EM_Clear, enable_cut);
  143.         SetItemEnable(mh, EM_SelectAll, enable_select_all);
  144.     end;
  145.  
  146.     procedure JustSelectTextItem (wt: WindowType; item: integer);
  147.     begin
  148.         if GetSelectedItem(wt) > 0 then begin
  149.             TextActivate(windowinfo[wt].items[GetSelectedItem(wt)]^.data, false);
  150.         end;
  151.         TextActivate(windowinfo[wt].items[item]^.data, (FrontWindow = windowinfo[wt].window) & InForeground);
  152.         windowinfo[wt].selected_item := item;
  153.     end; (* JustSelectTextItem *)
  154.  
  155.     procedure SelectTextItem (wt: WindowType; item: integer);
  156.     begin
  157.         JustSelectTextItem(wt, item);
  158.         TextSetSelect(windowinfo[wt].items[item]^.data, 0, 32767);
  159.     end;
  160.  
  161.     procedure DoTextMenu (wt: WindowType; menuitem: integer);
  162.         var
  163.             data: Ptr;
  164.             texth: Handle;
  165.             offset: longint;
  166.             search_text: integer;
  167.             cr_pos: longint;
  168.             item: integer;
  169.             text_size: longint;
  170.     begin
  171.         item := GetSelectedItem(wt);
  172.         data := windowinfo[wt].items[item]^.data;
  173.         case menuitem of
  174.             EM_Cut:  begin
  175.                 TextCut(data);
  176.             end;
  177.             EM_Copy:  begin
  178.                 TextCopy(data);
  179.             end;
  180.             EM_Paste: 
  181.                 if IsLocked(wt, item) then begin
  182.                     LockedAlert(wt, item);
  183.                 end
  184.                 else begin
  185.                     if btst(windowinfo[wt].items[item]^.flags, tf_single_line) then begin
  186.                         texth := NewHandle(0);
  187.                         if texth <> nil then begin
  188.                             offset := 0;
  189.                             text_size := GetScrap(texth, 'TEXT', offset);
  190.                             if text_size > 0 then begin
  191.                                 search_text := $0D0D;
  192.                                 cr_pos := Munger(texth, 0, @search_Text, 1, nil, 0);
  193.                                 if cr_pos > 0 then begin
  194.                                     SetHandleSize(texth, cr_pos);
  195.                                 end; (* if *)
  196.                                 TextClear(data);
  197.                                 TextInsert(data, texth);
  198.                             end; (* if *)
  199.                         end; (* if *)
  200.                         DisposeHandle(texth);
  201.                     end
  202.                     else begin
  203.                         TextPaste(data);
  204.                     end; (* if *)
  205.                 end; (* if *)
  206.             EM_Clear:  begin
  207.                 if IsLocked(wt, item) then begin
  208.                     LockedAlert(wt, item);
  209.                 end
  210.                 else begin
  211.                     TextClear(data);
  212.                 end; (* if *)
  213.             end;
  214.             EM_SelectAll:  begin
  215.                 TextSetSelect(data, 0, 32767);
  216.             end;
  217.             otherwise
  218.                 ;
  219.         end; (* case *)
  220.     end; (* DoTextMenu *)
  221.  
  222.     type
  223.         memBlock = packed array[0..16000000] of byte;
  224.         memBlockPtr = ^memBlock;
  225.  
  226.     function BlockCompare (lhs, rhs: univ Ptr; size: longint): boolean;
  227.         var
  228.             i: longint;
  229.             tmplhs, tmprhs: memBlockPtr;
  230.     begin
  231.         BlockCompare := false;
  232.         tmplhs := memBlockPtr(lhs);
  233.         tmprhs := memBlockPtr(rhs);
  234.         for i := 0 to size - 1 do begin
  235.             if tmplhs^[i] <> tmprhs^[i] then begin
  236.                 exit(BlockCompare);
  237.             end; (* if *)
  238.         end; (* for *)
  239.         BlockCompare := true;
  240.     end; (* BlockCompare *)
  241.  
  242.     procedure ScrambleHandle (texth: Handle);
  243.         var
  244.             l: longint;
  245.             tmptext: memBlockPtr;
  246.     begin
  247.         tmptext := memBlockPtr(texth^);
  248.         for l := 1 to GetHandleSize(texth) do begin
  249.             tmptext^[l - 1] := band(bxor(tmptext^[l - 1], $55 + l), $FF);
  250.         end; (* for *)
  251.     end; (* ScrambleHandle *)
  252.  
  253. {$PUSH}
  254. {$R-}
  255.     procedure BlockFill (p: univ ptr; len: longInt; value: integer);
  256.     begin
  257.         while (len > 0) do begin
  258.             p^ := value;
  259.             len := len - 1;
  260.             longInt(p) := longInt(p) + 1;
  261.         end;
  262.     end;
  263. {$POP}
  264.  
  265.     function WhatOpenText (wt: WindowType; item: integer): OSErr;
  266.         var
  267.             err: OSErr;
  268.             key: Str31;
  269.             attr: longint;
  270.             texth: Handle;
  271.             textsize: longint;
  272.             junk: longint;
  273.             flags: longint;
  274.             pstring: boolean;
  275.             scrambled: boolean;
  276.             font, size: integer;
  277.             r: Rect;
  278.     begin
  279.         windowinfo[wt].items[item]^.data := nil;
  280.         windowinfo[wt].items[item]^.spare_data := nil;
  281.         texth := nil;
  282.         key := windowinfo[wt].items[item]^.key;
  283.         flags := windowinfo[wt].items[item]^.flags;
  284.         pstring := btst(flags, tf_pstring);
  285.         scrambled := btst(flags, tf_scrambled);
  286.         if btst(flags, tf_monospace) then begin
  287.             font := monaco;
  288.             size := 9;
  289.         end
  290.         else begin
  291.             font := systemFont;
  292.             size := 12;
  293.         end; (* if *)
  294.         err := ICMapErr(ICGetPrefHandle(GetInstance, key, attr, texth));
  295.         if err = noErr then begin
  296.             ProcessAttributes(wt, item, attr);
  297.             if pstring then begin
  298.                 junk := Munger(texth, 0, nil, 1, @junk, 0);
  299.             end; (* if *)
  300.             if scrambled then begin
  301.                 ScrambleHandle(texth);
  302.             end; (* if *)
  303.             err := TextCreate(windowinfo[wt].items[item]^.data, windowinfo[wt].window, item, font, size, IsLocked(wt, item));
  304.         end; (* if *)
  305.         if err = noErr then begin
  306.             SetDItemHandle(windowinfo[wt].window, item, @DrawTextProc);
  307.             TextInsert(windowinfo[wt].items[item]^.data, texth);
  308.         end; (* if *)
  309.         if (err = noErr) & scrambled then begin
  310.             windowinfo[wt].items[item]^.spare_data := windowinfo[wt].items[item]^.data;
  311.             windowinfo[wt].items[item]^.data := nil;
  312.             GetDItemRect(windowinfo[wt].window, item, r);
  313.             OffsetRect(r, 16000, 0);
  314.             TextMove(windowinfo[wt].items[item]^.spare_data, r);
  315.             BlockFill(texth^, GetHandleSize(texth), ord('•'));
  316.             err := TextCreate(windowinfo[wt].items[item]^.data, windowinfo[wt].window, item, font, size, IsLocked(wt, item));
  317.             if err = noErr then begin
  318.                 TextInsert(windowinfo[wt].items[item]^.data, texth);
  319.             end; (* if *)
  320.         end; (* if *)
  321.         if texth <> nil then begin
  322.             DisposeHandle(texth);
  323.         end; (* if *)
  324.         WhatOpenText := err;
  325.     end; (* WhatOpenText *)
  326.  
  327. (* *)
  328.  
  329.     function WhatFlushText (wt: WindowType; item: integer): OSErr;
  330.         var
  331.             err: OSErr;
  332.             key: Str31;
  333.             texth: Handle;
  334.             oldtexth: Handle;
  335.             attr: longint;
  336.             junk: longint;
  337.             i: integer;
  338.             flags: longint;
  339.             pstring: boolean;
  340.             scrambled: boolean;
  341.     begin
  342.         texth := nil;
  343.         oldtexth := nil;
  344.         key := windowinfo[wt].items[item]^.key;
  345.         flags := windowinfo[wt].items[item]^.flags;
  346.         pstring := btst(flags, tf_pstring);
  347.         scrambled := btst(flags, tf_scrambled);
  348.         err := ICMapErr(ICGetPrefHandle(GetInstance, key, attr, oldtexth));
  349.         if err = noErr then begin
  350.             if pstring and (GetHandleSize(oldtexth) = 0) then begin
  351.                 SetHandleSize(oldtexth, 1);
  352.                 err := MemError;
  353.                 if err = noErr then begin
  354.                     oldtexth^^ := 0;
  355.                 end; (* if *)
  356.             end; (* if *)
  357.         end; (* if *)
  358.         if err = noErr then begin
  359.             texth := NewHandle(0);
  360.             err := MemError;
  361.         end; (* if *)
  362.         if err = noErr then begin
  363.             if scrambled then begin
  364.                 TextGet(windowinfo[wt].items[item]^.spare_data, texth);
  365.             end
  366.             else begin
  367.                 TextGet(windowinfo[wt].items[item]^.data, texth);
  368.             end; (* if *)
  369.             if scrambled then begin
  370.                 ScrambleHandle(texth);
  371.             end; (* if *)
  372.             if pstring then begin
  373.                 if GetHandleSize(texth) > 255 then begin
  374.                     SetHandleSize(texth, 255);
  375.                 end; (* if *)
  376.                 i := GetHandleSize(texth) * $0101;                    (* puts it into both bytes! *)
  377.                 junk := Munger(texth, 0, nil, 0, @i, 1);            (* if this errors, we lose *)
  378.             end; (* if *)
  379.             if not IsLocked(wt, item) & ((GetHandleSize(texth) <> GetHandleSize(oldtexth)) | not BlockCompare(texth^, oldtexth^, GetHandleSize(texth))) then begin
  380.                 err := ICMapErr(ICSetPrefHandle(GetInstance, key, ICattr_no_change, texth));
  381.                 if err = noErr then begin
  382.                     DirtyDocument;
  383.                 end; (* if *)
  384.             end; (* if *)
  385.         end; (* if *)
  386.         if texth <> nil then begin
  387.             DisposeHandle(texth);
  388.         end; (* if *)
  389.         if oldtexth <> nil then begin
  390.             DisposeHandle(oldtexth);
  391.         end; (* if *)
  392.         WhatFlushText := err;
  393.     end; (* WhatFlushText *)
  394.  
  395. (* *)
  396.  
  397.     function WhatCloseText (wt: WindowType; item: integer): OSErr;
  398.         var
  399.             flags: longint;
  400.             scrambled: boolean;
  401.     begin
  402.         flags := windowinfo[wt].items[item]^.flags;
  403.         scrambled := btst(flags, tf_scrambled);
  404.         TextDestroy(windowinfo[wt].items[item]^.data);
  405.         if scrambled then begin
  406.             TextDestroy(windowinfo[wt].items[item]^.spare_data);
  407.         end; (* if *)
  408.         WhatCloseText := noErr;
  409.     end; (* WhatCloseText *)
  410.  
  411. (* *)
  412.  
  413.     function WhatClickText (wt: WindowType; item: integer; er: eventRecord): OSErr;
  414.     begin
  415.         JustSelectTextItem(wt, item);
  416.         TextClick(windowinfo[wt].items[item]^.data, er);
  417.         WhatClickText := noErr;
  418.     end; (* WhatClickText *)
  419.  
  420.     function WhatKeyText (wt: WindowType; item: integer; er: EventRecord): OSErr;
  421.         var
  422.             flags: longint;
  423.             scrambled: boolean;
  424.             ch: char;
  425.             sel_start, sel_end: integer;
  426.     begin
  427.         flags := windowinfo[wt].items[item]^.flags;
  428.         scrambled := btst(flags, tf_scrambled);
  429.         ch := chr(BAND(er.message, charCodeMask));
  430.         if (btst(flags, tf_single_line) and (ch = chr(13))) or (scrambled and ((ch <> chr(8)) and (ch < ' '))) then begin
  431.             SysBeep(1);
  432.         end
  433.         else begin
  434.             if IsLocked(wt, item) and DirtyKey(ch) then begin
  435.                 LockedAlert(wt, item);
  436.             end
  437.             else begin
  438.                 if scrambled then begin
  439.                     TextGetSelect(windowinfo[wt].items[item]^.data, sel_start, sel_end);
  440.                     TextSetSelect(windowinfo[wt].items[item]^.spare_data, sel_start, sel_end);
  441.                     TextKey(windowinfo[wt].items[item]^.spare_data, er);
  442.                     if (ch <> chr(8)) & DirtyKey(ch) then begin
  443.                         er.message := ord('•');
  444.                     end;
  445.                     TextKey(windowinfo[wt].items[item]^.data, er);
  446.                 end
  447.                 else begin
  448.                     TextKey(windowinfo[wt].items[item]^.data, er);
  449.                 end; (* if *)
  450.             end; (* if *)
  451.         end; (* if *)
  452.         WhatKeyText := noErr;
  453.     end; (* WhatKeyText *)
  454.  
  455. end. (* TextWhats *)